package com.kymatrix.kycarbon.xsmd.system.server.service.impl;

import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.kymatrix.kycarbon.xsmd.system.server.model.entity.TenantEntity;
import com.kymatrix.kycarbon.xsmd.system.server.model.entity.TokenEntity;
import com.kymatrix.kycarbon.xsmd.system.server.model.entity.UserEntity;
import com.kymatrix.kycarbon.xsmd.system.server.service.ITokenService;
import com.kymatrix.kycarbon.xsmd.system.server.service.IUserService;
import com.kymatrix.kycarbon.xsmd.common.redis.util.RedisUtil;
import com.kymatrix.kycarbon.xsmd.common.springsecurity.LoginUser;
import com.kymatrix.kycarbon.xsmd.common.util.JwtUtil;
import com.kymatrix.kycarbon.xsmd.system.server.service.ITenantService;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * @author liujie
 * @date 2024-04-16
 */
@Service
@Slf4j
public class TokenServiceImpl implements ITokenService {

    @Resource
    private IUserService userService;
    @Resource
    private ITenantService tenantService;
    @Resource
    private RedisUtil redisUtil;

    @Override
    public String generateToken(String userId, boolean autoLoginFlag) {

        UserEntity userEntity = this.userService.getById(userId);
        long expirationSeconds = autoLoginFlag ? JwtUtil.getAutoLoginExpiration().getSeconds() 
                : JwtUtil.getExpiration().getSeconds();
        String token = autoLoginFlag ? JwtUtil.generateToken(
                userEntity.getUsername(), userEntity.getTenantId(), JwtUtil.getAutoLoginExpiration()) :
                JwtUtil.generateToken(
                        userEntity.getUsername(), userEntity.getTenantId(), JwtUtil.getExpiration());
        TokenEntity tokenEntity = new TokenEntity()
                .setUserId(userId)
                .setTenantId(userEntity.getTenantId())
                .setUserInfo(buildUserInfo(userEntity))
                .setAccessToken(token)
                .setExpiresTime(LocalDateTime.now().plusSeconds(expirationSeconds));
        String tokenValue = JSON.toJSONString(tokenEntity);
        redisUtil.set(token, tokenValue, expirationSeconds);
        return token;
    }

    @Override
    public LoginUser checkAccessToken(String accessToken) {
        Object obj = redisUtil.get(accessToken);
        if (obj != null) {
            TokenEntity tokenEntity = JSON.parseObject(obj.toString(), TokenEntity.class);
            UserEntity userEntity = this.userService.getById(tokenEntity.getUserId());
            TenantEntity tenantEntity = this.tenantService.getById(tokenEntity.getTenantId());
            if (userEntity == null || tenantEntity == null
                || !Objects.equals(userEntity.getTenantId(), tokenEntity.getTenantId())) {
                log.warn("校验token={}未通过, userEntity={}, tenantEntity={}", accessToken, userEntity, tenantEntity);
                return null;
            }
            LoginUser loginUser = new LoginUser();
            loginUser.setId(tokenEntity.getUserId());
            loginUser.setUsername(userEntity.getUsername());
            loginUser.setTenantId(tokenEntity.getTenantId());
            loginUser.setUserInfo(tokenEntity.getUserInfo());
            return loginUser;
        }
        return null;
    }

    @Override
    public void removeToken(String token) {
        redisUtil.del(token);
    }

    private Map<String, String> buildUserInfo(UserEntity userEntity) {
        return MapUtil.builder("phone", userEntity.getPhone())
                .put("email", userEntity.getEmail()).build();
    }
}
